﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Controls;
using Windows.UI.Text;

using Coder.Framework;

namespace Coder.ViewModel
{
    public class EditorViewModel : Bindable
    {
        RichEditBox _mainEditor;
        RichEditBox MainEditor
        {
            get { return _mainEditor; }
            set
            {
                _mainEditor = value;
                PropertyChangedEvent("MainEditor");
            }
        }

        Project _project;
        Project CurrentProject { get { return _project; } set { _project = value; PropertyChangedEvent("CurrentProject"); } }

        /// <summary>
        /// Sets up the EditorViewModel
        /// </summary>
        /// <param name="currentEditorBox">Requires the current formatted RichEditBox.</param>
        /// <param name="currentProject">The Current Project the User wants to modify.</param>
        public EditorViewModel(RichEditBox currentEditorBox, Project currentProject)
        {
            MainEditor = currentEditorBox;
            
            //Sets the MainEditor text to the projects existant code.
            MainEditor.Document.SetText(TextSetOptions.None, currentProject.Code);

            CurrentProject = currentProject;

            MainEditor.KeyDown += MainEditor_KeyDown;
        }


        /// <summary>
        /// Manages the users Key Presses.
        /// </summary>
        /// <param name="e">Represents the Key that was pressed.</param>
        private void MainEditor_KeyDown(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key == Windows.System.VirtualKey.Tab)
            {
                MainEditor.Document.Selection.TypeText("\t");
            }
                /*
            else if (e.Key == Windows.System.VirtualKey.Space)
            {

                //MainEditor.Document.Selection.TypeText(" ");
            }
            */
            FormatEditor();
        }

        /// <summary>
        /// Formats the Editor with the Key Words associated with each language.  Uses the Key Word dictionary found in the Language.
        /// </summary>
        private void FormatEditor()
        {
            string code;
            MainEditor.Document.GetText(TextGetOptions.None, out code);

            //Sets everything to default formatting.
            MainEditor.Document.GetRange(0, code.Length).CharacterFormat.ForegroundColor = Windows.UI.Colors.Black;
            MainEditor.Document.GetRange(0, code.Length).CharacterFormat.FontStyle = FontStyle.Normal;

            //Goes through each Keyword.
            foreach (KeyValuePair<string, int> keyword in CurrentProject.Language.KeyWords)
            {
                int index = 0;
                while (index < code.Length)
                {
                    int positionIndex = code.IndexOf(keyword.Key, index, StringComparison.OrdinalIgnoreCase);
                    
                    bool continueColoring = true;
                    if (positionIndex > -1)
                    {
                        //Check if the Key Word is not within another word.
                        if (positionIndex + keyword.Key.Length + 1 < code.Length && positionIndex - 1 > -1) //Let's make sure we are within the bounds of the code string.
                        {
                            if (!(code[positionIndex - 1] == ' ' || code[positionIndex - 1] == '\r' || code[positionIndex - 1] == '\n'))
                            {
                                continueColoring = false;
                            }
                            if (!(code[positionIndex + keyword.Key.Length + 1] == ' ' || code[positionIndex + keyword.Key.Length + 1] == '\r'
                                || code[positionIndex + keyword.Key.Length + 1] == '\n'))
                            {
                                continueColoring = false;
                            }
                        }
                        if (continueColoring)
                        {
                            switch (CurrentProject.Language.KeyWords[keyword.Key])
                            {
                                case 0:
                                    MainEditor.Document.GetRange(positionIndex, positionIndex + keyword.Key.Length).CharacterFormat.ForegroundColor = Windows.UI.Colors.Blue;
                                    break;
                                case 1:
                                    MainEditor.Document.GetRange(positionIndex, positionIndex + keyword.Key.Length).CharacterFormat.ForegroundColor = Windows.UI.Colors.Red;
                                    break;
                                case 2:
                                    MainEditor.Document.GetRange(positionIndex, positionIndex + keyword.Key.Length).CharacterFormat.ForegroundColor = Windows.UI.Colors.Blue;
                                    break;
                            }
                        }

                        index = positionIndex + 1;
                    }
                    else
                    {
                        index = code.Length; //Let's leave this while loop.
                    }
                }
            }

            //Time to find the comments...they usually end in /n.
            int cIndex = 0;
            while (cIndex < code.Length)
            {
                int cPositionIndex = code.IndexOf("//", cIndex, StringComparison.OrdinalIgnoreCase);
                if (cPositionIndex > -1)
                {
                    int cEndPositionIndex = code.IndexOf("\r", cPositionIndex);
                    if (cEndPositionIndex > -1)
                    {
                        MainEditor.Document.GetRange(cPositionIndex, cEndPositionIndex).CharacterFormat.ForegroundColor = Windows.UI.Colors.Green;
                    }
                    cIndex = cPositionIndex + 1;
                }
                else
                {
                    cIndex = code.Length; //Let's leave the loop.
                }

            }
        }

    }
}
